package com.xnyzc.lhy.order.service.impl.work;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xnyzc.lhy.common.component.redis.RedisCommon;
import com.xnyzc.lhy.common.constant.RedisPrefixConstant;
import com.xnyzc.lhy.common.entity.Qw;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.driver.EServiceFraction;
import com.xnyzc.lhy.common.penum.work.EPunchType;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.DateUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.common.util.TokenUtil;
import com.xnyzc.lhy.order.entity.user.OaDUserInfo;
import com.xnyzc.lhy.order.entity.work.*;
import com.xnyzc.lhy.order.mapper.user.OaDUserInfoMapper;
import com.xnyzc.lhy.order.mapper.work.*;
import com.xnyzc.lhy.order.service.work.IOaCommutRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 管理员、司机-通勤记录表 服务实现类
 * 没写完先提交了
 * </p>
 *
 * @author zhuyubin
 * @since 2019-08-05
 */
@Slf4j
@Service
public class OaCommutRecordServiceImpl extends ServiceImpl<OaCommutRecordMapper, OaCommutRecord> implements IOaCommutRecordService {

    @Autowired
    private OaCommutUserMapper oaCommutUserMapper;
    @Autowired
    private OaCommutConfigMapper oaCommutConfigMapper;
    @Autowired
    private OaCommutRecordMapper oaCommutRecordMapper;
    @Autowired
    private RedisCommon redisCommon;
    @Autowired
    private OaDWorkStatisticsMapper oaDWorkStatisticsMapper;
    @Autowired
    private OaDUserInfoMapper oaDUserInfoMapper;

    @Autowired
    private OaDWorkRecordMapper workRecordMapper;

    /**
     * 打卡
     *
     * @param userId       管理员或司机id
     * @param userType     用户状态
     * @param tag          租户
     * @param punchType    打卡类型
     * @param punchAddress 打卡地址
     * @param punchLng     打卡经度
     * @param punchLat     打卡纬度
     * @return
     */
    @Override
    public String commutRecord(
            Long userId,
            Integer userType,
            String tag,
            Integer punchType,
            String punchAddress,
            String punchLng,
            String punchLat
    ) {
        Date date = new Date();
        long startTime = DateUtil.getDayStartTimeNew(date).getTime();
        // 司机日统计键
        String workStatisticsRedisKey = String.format("%s%s", RedisPrefixConstant.WORK_OA_D_WORK_STATISTICS, userId);
        // 上班
        if (EPunchType.goToWork.getType().equals(punchType)) {
            // 将redis数据转为实体
            String workStatisticsJsonStr = redisCommon.getStr(workStatisticsRedisKey);
            // redis没有未更新下来的数据
            if (CheckUtil.objIsNotEmpty(workStatisticsJsonStr)){
                // 将redis数据更新到数据库
                OaDWorkStatistics oaDWorkStatistics = JSON.parseObject(workStatisticsJsonStr, OaDWorkStatistics.class);
                oaDWorkStatistics.setUpdateTime(date);
                oaDWorkStatistics.setUpdateUser(userId);
                oaDWorkStatisticsMapper.updateById(oaDWorkStatistics);
            }
            // 司机日考勤表
            List<OaDWorkStatistics> oaDWorkStatisticsList = oaDWorkStatisticsMapper.selectList(
                    Wrappers.<OaDWorkStatistics>lambdaQuery()
                            .eq(OaDWorkStatistics::getTag, tag)
                            .eq(OaDWorkStatistics::getDriverId, userId)
                            .orderByDesc(OaDWorkStatistics::getCreateTime));
            // 获取打卡
            if (CheckUtil.objIsNotEmpty(oaDWorkStatisticsList)){
                OaDWorkStatistics oaDWorkStatistics = oaDWorkStatisticsList.get(0);
                Date createTime = oaDWorkStatistics.getCreateTime();
                // 今天第一次打卡
                if (createTime.getTime() < startTime){
                    // 初始化司机日统计
                    OaDWorkStatistics workStatistics = this.initWorkStatistics(userId, tag, date);
                    // 推送到redis
                    redisCommon.set(workStatisticsRedisKey, JSON.toJSONString(workStatistics));
                }
                // 今天多次打卡
                else {
                    // 推送到redis
                    redisCommon.set(workStatisticsRedisKey, JSON.toJSONString(oaDWorkStatistics));
                }
            }
            // 新司机一次打卡记录都没有
            else {
                // 初始化司机日统计
                OaDWorkStatistics workStatistics = this.initWorkStatistics(userId, tag, date);
                // 推送到redis
                redisCommon.set(workStatisticsRedisKey, JSON.toJSONString(workStatistics));
            }
        }
        // 下班
        else {
            // 是否接单
            List list = workRecordMapper.selectList(Qw.create().eq(OaDWorkRecord.DRIVER_ID, TokenUtil.getTokenUserId()).isNull(OaDWorkRecord.END_TIME));
            if (CheckUtil.collectionIsNotEmpty(list)) {
                throw PangException.create(EErrorCode.notPunch);
            }
            // 更新redis数据到数据库
            String  workStatisticsJsonStr = redisCommon.getStr(workStatisticsRedisKey);
            if (CheckUtil.objIsNotEmpty(workStatisticsJsonStr)) {
                // 将redis数据更新到数据库
                OaDWorkStatistics oaDWorkStatistics = JSON.parseObject(workStatisticsJsonStr, OaDWorkStatistics.class);
                OaDWorkStatistics workStatistics = oaDWorkStatisticsMapper.selectById(oaDWorkStatistics.getStatisticsId());
                if (CheckUtil.objIsEmpty(workStatistics)){
                    log.info("数据库未查到司机日统计记录");
                    throw PangException.create(EErrorCode.commutFailure);
                }
                oaDWorkStatistics.setVersion(workStatistics.getVersion());
                oaDWorkStatistics.setUpdateTime(date);
                oaDWorkStatistics.setUpdateUser(userId);
                int i = oaDWorkStatisticsMapper.updateById(oaDWorkStatistics);
                if (i != 1) {
                    throw PangException.create(EErrorCode.commutFailure);
                }
                redisCommon.remove(workStatisticsRedisKey);
            }
            //清除休息时长
            redisCommon.remove(String.format("%s%s", RedisPrefixConstant.WORK_OA_D_WORK_RECORD, userId));
        }
        this.insertCommutRecord(userId, userType, punchAddress, punchLng, punchLat, punchType, tag);
        return EErrorCode.commutSuccess.getDesc();
    }

    /**
     * 插入打卡记录
     *
     * @param userId       管理员或司机id
     * @param userType     用户类型
     * @param punchAddress 打卡地址
     * @param punchLng     打卡经度
     * @param punchLat     打卡纬度
     * @param punchType    打卡类型
     * @param tag          租户
     */
    private void insertCommutRecord(
            Long userId,
            Integer userType,
            String punchAddress,
            String punchLng,
            String punchLat,
            Integer punchType,
            String tag
    ) {
        Date date = new Date();
        OaCommutRecord oaCommutRecord = new OaCommutRecord();
        oaCommutRecord.setRecordId(IDUtil.nextId());
        oaCommutRecord.setUserId(userId);
        oaCommutRecord.setUserType(userType);
        oaCommutRecord.setPunchTime(date);
        oaCommutRecord.setPunchAddress(punchAddress);
        oaCommutRecord.setPunchLng(punchLng);
        oaCommutRecord.setPunchLat(punchLat);
        oaCommutRecord.setPunchType(punchType);
        /*oaCommutRecord.setPunchStatus(ePunchStatus.getType());*/
        oaCommutRecord.setTag(tag);
        oaCommutRecord.setCreateUser(userId);
        oaCommutRecord.setCreateTime(date);
        oaCommutRecord.setUpdateUser(userId);
        oaCommutRecord.setUpdateTime(date);
        int insert = oaCommutRecordMapper.insert(oaCommutRecord);
        if (insert != 1) {
            throw PangException.create(EErrorCode.commutFailure);
        }
    }

    /**
     * 获取打卡配置
     *
     * @param driverId 司机或管理员id
     * @param tag      租户
     * @param userType 用户类型
     * @return
     */
    @Override
    public OaCommutConfig getCommutConfig(Long driverId, String tag, Integer userType) {
        OaCommutUser oaCommutUser = oaCommutUserMapper.selectOne(
                Wrappers.<OaCommutUser>lambdaQuery()
                        .eq(OaCommutUser::getUserId, driverId)
                        .eq(OaCommutUser::getUserType, userType)
                        .eq(OaCommutUser::getTag, tag)
        );
        if (CheckUtil.objIsEmpty(oaCommutUser)) {
            throw PangException.create(EErrorCode.commutFailure);
        }
        // 考勤配置id
        Long configId = oaCommutUser.getConfigId();
        // 考勤配置
        OaCommutConfig oaCommutConfig = oaCommutConfigMapper.selectById(configId);
        if (CheckUtil.objIsEmpty(oaCommutConfig)) {
            throw PangException.create(EErrorCode.commutFailure);
        }
        return oaCommutConfig;
    }

    /**
     * 查询当天打卡记录
     *
     * @param userId   管理员或司机id
     * @param tag      租户
     * @param userType 用户类型
     * @return
     */
    @Override
    public boolean selectCommutRecord(Long userId, String tag, Integer userType) {
        /*Date date = new Date();
        Timestamp dayStartTime = DateUtil.getDayStartTime(date);
        Timestamp dayEndTime = DateUtil.getDayEndTime(date);*/
        List<OaCommutRecord> oaCommutRecords = oaCommutRecordMapper.selectList(
                Wrappers.<OaCommutRecord>lambdaQuery()
                        /*.ge(OaCommutRecord::getCreateTime, new Date(dayStartTime.getTime()))
                        .le(OaCommutRecord::getCreateTime, new Date(dayEndTime.getTime()))*/
                        .eq(OaCommutRecord::getUserId, userId)
                        .eq(OaCommutRecord::getTag, tag)
                        .eq(OaCommutRecord::getUserType, userType)
                        .orderByDesc(OaCommutRecord::getCreateTime)
        );
        if (oaCommutRecords.size() <= 0) {
            return false;
        }
        OaCommutRecord oaCommutRecord = oaCommutRecords.get(0);
        if (EPunchType.offWork.getType().equals(oaCommutRecord.getPunchType())) {
            return false;
        }
        return true;
    }

    /**
     * 初始化 当日司机日统计
     * @param userId 管理员或司机id
     * @param tag 租户
     * @param date 当前时间
     */
    private OaDWorkStatistics initWorkStatistics(Long userId, String tag, Date date){
        OaDWorkStatistics workStatistics = new OaDWorkStatistics();
        workStatistics.setStatisticsId(IDUtil.nextId());
        workStatistics.setDriverId(userId);
        workStatistics.setDayTotalCost("0");
        workStatistics.setDayOrderNumber(0);
        workStatistics.setDayOnlineTime(0);
        workStatistics.setDayServiceTime(0);
        workStatistics.setDayDrivenDistance(0);
        List<OaDUserInfo> oaDUserInfoList = oaDUserInfoMapper.selectList(Wrappers.<OaDUserInfo>lambdaQuery().eq(OaDUserInfo::getTag, tag).eq(OaDUserInfo::getDriverId, userId));
        if (oaDUserInfoList.size() == 1){
            Integer totalServiceScore = oaDUserInfoList.get(0).getTotalServiceScore();
            if (CheckUtil.objIsNotEmpty(totalServiceScore)){
                workStatistics.setTotalServiceScore(oaDUserInfoList.get(0).getTotalServiceScore());
            } else {
                workStatistics.setTotalServiceScore(EServiceFraction.serviceFraction.getValue());
            }
        } else {
            workStatistics.setTotalServiceScore(EServiceFraction.serviceFraction.getValue());
        }
        // Date 转 LocalDate
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
        workStatistics.setStatisticsTime(localDate);
        workStatistics.setTag(tag);
        workStatistics.setCreateUser(userId);
        workStatistics.setCreateTime(date);
        workStatistics.setUpdateUser(userId);
        workStatistics.setUpdateTime(date);
        workStatistics.setDayServerTime(0);
        workStatistics.setDayOrderTime(0);
        workStatistics.setDayRestTime(0);
        int i = oaDWorkStatisticsMapper.insert(workStatistics);
        if (i != 1){
            throw PangException.create(EErrorCode.commutFailure);
        }
        return workStatistics;
    }
}
